package org.zn.note.mybatis.core.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Jdk代理
 * 接口 {@link HelloService}，实现类 {@link HelloServiceImpl}
 * 1、Jdk静态代理，代理类里写死的实现类，绑死了，例子：{@link JdkStaticProxy}
 * 2、Jdk动态代理，利用反射在运行时创建代理类(class)。必须依赖接口，而CGLIB不用。
 */
public class JdkProxyHandler implements InvocationHandler {

    private Object target;

    JdkProxyHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.printf("Start JdkProxyHandler.invoke execute %s.%s !\n",
                target.getClass().getSimpleName(), method.getName());
        Object result = method.invoke(target, args);
        System.out.printf("Finish JdkProxyHandler.invoke execute %s.%s !\n",
                target.getClass().getSimpleName(), method.getName());
        return result;
    }

    public static void main(String[] args) {

        // 是否保存代理类class文件 （保存位置：项目同级目录下/com/sun/proxy）
//        System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

        // 实现类
        HelloService impl = new HelloServiceImpl();
        InvocationHandler handler = new JdkProxyHandler(impl);
        // 代理类
        // 这个过程就是：Jdk生成了代理类，然后代理类执行的具体行为是你写的handler
        // 这样只需要定义“代理行为”，然后Jdk会根据 实现类(被代理的类) + “代理行为” 生成代理类对象
        HelloService proxy =
                (HelloService) Proxy.newProxyInstance( // Jdk生成代理对象
                        impl.getClass().getClassLoader(), // 类加载器
                        impl.getClass().getInterfaces(), // 被代理的对象的接口，生成的代理类同样实现这些接口
                        handler); // 代理对象的具体实现(执行者)

        proxy.sayHello("zzz");
    }
}
